﻿using Bll;
using Entity.BBC;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Utils;

namespace Analysis.Controllers
{
    public class LoginManagerController : Controller
    {
        // GET: LoginManager
        public ActionResult Index()
        {
            String codeUrl = GetCodeUrl();
            // LogHelper.WriteInfoLog("code 授权地址:" + codeUrl);
            return Redirect(codeUrl);
        }

        public ActionResult DisIndex()
        {
            String codeUrl = GetDisCodeUrl();
            return Redirect(codeUrl);
        }


        public ActionResult UserLogin(string userName, string userPass)
        {
            Session["User"] = null;
            String sqlStr = string.Format("SELECT * FROM [User] WHERE Effected=1 AND AccountName='{0}'", userName);
            IList<User> userList = BllBBCCommon.SelectEntityBySql<User>("User", sqlStr);
            if (userList == null || userList.Count == 0)
            {
                // 用户名不存在
                return Content("-2");
            }
            User userInfo = userList[0];
            if (!userInfo.Effected)
            {
                // 您的账户还未激活
                return Content("-3");
            }
            if (!userInfo.AccountPassword.Equals(Encryption.EncryptMD5(userPass)))
            {
                // 密码错误
                return Content("-1");
            }
            Session["User"] = userInfo;
            return Content("1");
        }


        /// <summary>  
        /// 回调处理  
        /// </summary>  
        /// <returns></returns>  
        public ActionResult AuthLogin()
        {
            Session["User"] = null;
            string OpenID_Pub = "";
            #region 通过餐饮接口获取公众号OpenID
            try
            {
                //1.处理跳转  
                this.Code = Request.QueryString["code"];
                LogHelper.WriteInfoLog("第一步获取code : " + this.Code);
                //this.Code = Request["code"]; // Request.GetString("code");
                //LogHelper.WriteInfoLog("第二步获取code : " + this.Code);

                //第二步  
                GetAccess_Token();
                //第三步  
                // GetUserInfo();
                //显示结果  
                // ViewBag.msg = "AuthLogin : " + TokenData.openid;
                OpenID_Pub = TokenData.openid;
                LogHelper.WriteInfoLog("登录OpenID : " + OpenID_Pub);
            }
            catch (Exception ex)
            {
                LogHelper.WriteInfoLog("微信获取OpenID异常:" + ex.Message.ToString());
                // 访问接口异常 跳转登录界面
                return View();
            }
            #endregion
            if (OpenID_Pub == null || OpenID_Pub == "")
            {
                LogHelper.WriteInfoLog("没有获得OpenID 跳转登录界面");
                // 没有获得OpenID 跳转登录界面
                return View();
            }
            String sqlStr = string.Format("SELECT * FROM [User] WHERE Effected=1 AND AccountName IN(SELECT UserWeChat.AccountName FROM UserWeChat WHERE IsEffective=1 AND OpenID='{0}')", OpenID_Pub);
            IList<User> userList = BllBBCCommon.SelectEntityBySql<User>("User", sqlStr);
            if (userList == null || userList.Count == 0)
            {
                LogHelper.WriteInfoLog("通过OpenID没有获得用户信息 跳转登录界面");
                // 通过OpenID没有获得用户信息 跳转登录界面
                return View();
            }
            if (userList.Count > 1)
            {
                LogHelper.WriteInfoLog("多条用户信息, 未能确定具体用户 跳转登录界面");
                // 多条用户信息, 未能确定具体用户 跳转登录界面
                return View();
            }
            User userInfo = userList[0];
            if (!userInfo.Effected)
            {
                LogHelper.WriteInfoLog("账户还未激活 跳转登录界面");
                // 账户还未激活 跳转登录界面
                return View();
            }
            Session["User"] = userInfo;
            // return Redirect("PurchaEdit/Index");
            return RedirectToAction("Index", "PurchaEdit");
        }

        /// <summary>
        /// 回调处理, 显示OpenID
        /// </summary>
        /// <returns></returns>
        public ActionResult DisOpenID()
        {
            //1.处理跳转  
            this.Code = Request.QueryString["code"];
            LogHelper.WriteInfoLog("第一步获取code : " + this.Code);
            //this.Code = Request["code"]; // Request.GetString("code");
            //LogHelper.WriteInfoLog("第二步获取code : " + this.Code);

            //第二步  
            GetAccess_Token();
            //第三步  
            // GetUserInfo();
            //显示结果  
            ViewBag.msg = "您的OpenID是 : " + TokenData.openid;
            return View();
        }


        #region 基本信息定义
        /// <summary>  
        /// 公众号的唯一标识  
        /// </summary>  
        private string appid = "wx4fbadb12e5ea0937";
        /// <summary>  
        /// 公众号的appsecret  
        /// </summary>  
        private string secret = "5c8098a75a1c089bce1d0ea70b207ce2";
        /// <summary>  
        /// 回调url地址  
        /// </summary>  
        private string redirect_uri = "http://c.gxanr.com/Analysis/LoginManager/AuthLogin";
        private string dis_redirect_uri = "http://c.gxanr.com/Analysis/LoginManager/DisOpenID";

        /// <summary>  
        /// 获取微信用户基本信息使用snsapi_userinfo模式  
        /// 如果使用静默授权，无法获取用户基本信息但可以获取到openid 
        /// snsapi_base(不弹出授权页面，直接跳转，只能获取用户openid)
        /// snsapi_userinfo(弹出授权页面，可通过openid拿到昵称、性别、所在地。并且， 即使在未关注的情况下，只要用户授权，也能获取其信息)
        /// </summary>  
        private string scope = "snsapi_base";
        #endregion

        #region 请求过程信息
        /// <summary>  
        /// 第一步获取到的Code 值  
        /// </summary>  
        public string Code = null;
        /// <summary>  
        /// 第二步获取到的access_token及相关数据  
        /// </summary>  
        public AuthAccess_Token TokenData = null;
        #endregion

        #region 事件定义
        /// <summary>  
        /// 当处理出现异常时，触发  
        /// </summary>  
        public Action<Exception> OnError = null;
        /// <summary>  
        /// 当获取AccessToken成功是触发  
        /// </summary>  
        public Action<AuthAccess_Token> OnGetTokenSuccess = null;
        /// <summary>  
        /// 当获取用户信息成功时触发  
        /// </summary>  
        public Action<OAuthUser> OnGetUserInfoSuccess = null;
        #endregion

        #region 步骤 2,3,4
        /// <summary>  
        /// 第二步，通过code换取网页授权access_token  
        /// </summary>  
        public void GetAccess_Token()
        {
            try
            {
                //1.处理跳转  
                this.Code = Request.QueryString["code"];
                //LogHelper.WriteInfoLog("第二步获取code : "+this.Code);
                //this.Code = Request["code"]; // Request.GetString("code");
                //LogHelper.WriteInfoLog("第二步获取code : " + this.Code);
                if (string.IsNullOrEmpty(this.Code))
                    throw new Exception("获取code参数失败或用户禁止授权获取基本信息");
                //1.发送获取access_token请求  
                string url = GetAccess_TokenUrl();
                string result = NetGet(url);

                //2.解析相应结果  
                TokenData = JsonConvert.DeserializeObject<AuthAccess_Token>(result);
                if (TokenData == null)
                    throw new Exception("反序列化结果失败，返回内容为：" + result);
                //3.获取成功  
                if (OnGetTokenSuccess != null)
                    OnGetTokenSuccess(TokenData);
            }
            catch (Exception ex)
            {
                Error("第二步，通过code换取网页授权access_token异常", ex);
            }
        }
        /// <summary>  
        ///  第三步，刷新当前access_token  
        /// </summary>  
        public AuthAccess_Token RefreshAccess_Token()
        {
            try
            {
                //1.发送请求  
                string url = GetReferesh_TokenUrl();
                string result = NetGet(url);
                //2.解析结果
                AuthAccess_Token token = JsonConvert.DeserializeObject<AuthAccess_Token>(result);
                if (token == null)
                    throw new Exception("反序列化结果失败，返回内容：" + result);
                return token;
            }
            catch (Exception ex)
            {
                Error(" 第三步，刷新当前access_token失败", ex);
                return null;
            }
        }
        /// <summary>  
        /// 第四步，获取基本信息  
        /// </summary>  
        public void GetUserInfo()
        {
            try
            {
                //1.发送get请求  
                string url = GetUserInfoUrl();
                string result = NetGet(url);
                //2.解析结果  
                OAuthUser user = JsonConvert.DeserializeObject<OAuthUser>(result);
                if (user == null)
                    throw new Exception("反序列化结果失败，返回内容：" + result);
                //3.获取成功  
                if (OnGetUserInfoSuccess != null)
                    OnGetUserInfoSuccess(user);
            }
            catch (Exception ex)
            {
                Error("第四步、获取用户基本信息异常", ex);
            }
        }
        #endregion

        #region 静态方法
        /// <summary>  
        /// 验证授权凭证是否有效  
        /// </summary>  
        /// <param name="access_token">access_token</param>  
        /// <param name="openid">用户针对当前公众号的openid</param>  
        /// <returns></returns>  
        public static bool CheckWebAccess_Token(string access_token, string openid)
        {
            try
            {
                string url = string.Format("https://api.weixin.qq.com/sns/auth?access_token={0}&openid={1}", access_token, openid);
                string result = NetGet(url);
                JObject obj = JObject.Parse(result);
                int errcode = (int)obj["errcode"];
                return errcode == 0;
            }
            catch (Exception ex)
            {
                throw new Exception("，" + ex.Message);
            }
        }
        #endregion

        #region 获取请求连接
        /// <summary>  
        /// 获取Code的url 地址  
        /// </summary>  
        /// <returns></returns>  
        public string GetCodeUrl()
        {
            string url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=STATE#wechat_redirect", this.appid, System.Web.HttpUtility.UrlEncode(this.redirect_uri), this.scope);
            return url;
        }
        /// <summary>  
        /// 获取Code的url 地址  
        /// </summary>  
        /// <returns></returns>  
        public string GetDisCodeUrl()
        {
            string url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=STATE#wechat_redirect", this.appid, System.Web.HttpUtility.UrlEncode(this.dis_redirect_uri), this.scope);
            return url;
        }
        /// <summary>  
        /// 获取access_token的url地址  
        /// </summary>  
        /// <returns></returns>  
        private string GetAccess_TokenUrl()
        {
            string url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", this.appid, this.secret, this.Code);
            return url;
        }
        /// <summary>  
        /// 获取刷新AccessToke的地址  
        /// </summary>  
        /// <returns></returns>  
        private string GetReferesh_TokenUrl()
        {
            string url = string.Format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={0}&grant_type=refresh_token&refresh_token={1}", this.appid, this.TokenData.refresh_token);
            return url;
        }
        /// <summary>  
        /// 获取用户基本信息地址  
        /// </summary>  
        /// <returns></returns>  
        private string GetUserInfoUrl()
        {
            string url = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN", this.TokenData.access_token, this.TokenData.openid);
            return url;
        }
        #endregion

        #region   Http Get请求
        /// <summary>  
        /// 指定Url地址使用Get 方式获取全部字符串  
        /// </summary>  
        /// <param name="url">请求链接地址</param>  
        /// <returns></returns>  
        public static string NetGet(string url)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            try
            {
                //获取内容  
                using (StreamReader reader = new StreamReader(stream))
                {
                    result = reader.ReadToEnd();
                }
            }
            finally
            {
                stream.Close();
            }
            return result;
        }
        #endregion

        #region 相关 Model
        private void Error(string msg, Exception inner)
        {
            if (this.OnError != null)
            {
                this.OnError(new Exception(msg, inner));
            }
        }
        /// <summary>  
        /// 获取Access_Token或者刷新返回的数据对象  
        /// </summary>  
        public class AuthAccess_Token
        {
            public string access_token { get; set; }
            public int expires_in { get; set; }
            public string refresh_token { get; set; }
            /// <summary>  
            /// 用户针对当前公众号的唯一标识  
            /// 关注后会产生，返回公众号下页面也会产生  
            /// </summary>  
            public string openid { get; set; }
            public string scope { get; set; }
            /// <summary>  
            /// 当前用户的unionid，只有在用户将公众号绑定到微信开放平台帐号后  
            /// </summary>  
            public string unionid { get; set; }
        }
        /// <summary>  
        /// 授权之后获取用户基本信息  
        /// </summary>  
        public class OAuthUser
        {
            public string openid { get; set; }
            public string nickname { get; set; }
            public int sex { get; set; }
            public string province { get; set; }
            public string city { get; set; }
            public string country { get; set; }
            public string headimgurl { get; set; }
            /// <summary>  
            /// 用户特权信息，json 数组  
            /// </summary>  
            public JArray privilege { get; set; }
            public string unionid { get; set; }
        }
        #endregion
    }
}